package cn.shujuhai.common.service.impl;

import cn.shujuhai.common.domain.SysPermission;
import cn.shujuhai.common.domain.SysPermissionMenu;
import cn.shujuhai.common.domain.SysRolePermission;
import cn.shujuhai.common.mapper.SysPermissionMapper;
import cn.shujuhai.common.pluging.data.ResultCode;
import cn.shujuhai.common.pluging.data.ResultVo;
import cn.shujuhai.common.service.SysPermissionMenuService;
import cn.shujuhai.common.service.SysPermissionService;
import cn.shujuhai.common.service.SysRolePermissionService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import java.util.*;


/**
 * @author NiuYaHu
 * @description 针对表【sys_permission(权限表)】的数据库操作Service实现
 * @createDate 2024-10-25 10:01:15
 */
@Service
@RequiredArgsConstructor
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission>
        implements SysPermissionService {
    final SysRolePermissionService sysRolePermissionService;
    final SysPermissionMenuService sysPermissionMenuService;

    /**
     * 新增权限
     *
     * @param sysPermission 新增权限对象
     * @return 权限对象
     */
    @Override
    public ResultVo<?> savePermission(@Validated SysPermission sysPermission) {
        if (sysPermission.getPermissionParentId() == null) {
            sysPermission.setPermissionParentId(0L);
        }
        if (this.save(sysPermission)) {
            return ResultVo.success(sysPermission);
        }
        return ResultVo.failure(ResultCode.FAILED);
    }

    /**
     * 获取权限列表
     *
     * @return 返回对应的系统权限对象（SysPermission），如果未找到则返回null
     */
    @Override
    public ResultVo<?> getPermissionList() {
        return ResultVo.success(this.list());
    }

    /**
     * 根据权限Id删除权限
     *
     * @param permissionId 权限Id
     * @return 删除成功或失败的结果及响应信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> removePermissionById(Long permissionId) {
        Set<Long> allPermissionIds = getAllPermissionIds(permissionId);
        allPermissionIds.add(permissionId);
        QueryWrapper<SysRolePermission> rolePermissionQueryWrapper = new QueryWrapper<>();
        rolePermissionQueryWrapper.lambda().in(SysRolePermission::getPermissionId, allPermissionIds);
        List<SysRolePermission> sysRolePermissionList = this.sysRolePermissionService.list(rolePermissionQueryWrapper);
        QueryWrapper<SysPermissionMenu> sysPermissionMenuQueryWrapper = new QueryWrapper<>();
        sysPermissionMenuQueryWrapper.lambda().in(SysPermissionMenu::getPermissionId, allPermissionIds);
        List<SysPermissionMenu> sysPermissionMenuList = this.sysPermissionMenuService.list(sysPermissionMenuQueryWrapper);
        if (!sysRolePermissionList.isEmpty() || !sysPermissionMenuList.isEmpty()) {
            return ResultVo.failure(ResultCode.NO_REMOVE);
        }
        if (!this.removeByIds(allPermissionIds)) {
            return ResultVo.failure(ResultCode.FAILED);
        }
        return ResultVo.success();
    }

    /**
     * 根据权限Id查询角色Id
     *
     * @param permissionId 权限Id
     * @return 返回角色列表
     */
    @Override
    public ResultVo<?> getRoleIdsByPermissionId(Long permissionId) {
        Set<Long> allPermissionIds = getAllPermissionIds(permissionId);
        allPermissionIds.add(permissionId);
        QueryWrapper<SysRolePermission> rolePermissionQueryWrapper = new QueryWrapper<>();
        rolePermissionQueryWrapper.lambda().in(SysRolePermission::getPermissionId, allPermissionIds);
        List<SysRolePermission> sysRolePermissionList = this.sysRolePermissionService.list(rolePermissionQueryWrapper);
        return ResultVo.success(sysRolePermissionList);
    }

    /**
     * 递归查询一个权限下的所有子权限
     *
     * @param parentId 父id
     * @return 子权限集合
     */
    public Set<Long> getAllPermissionIds(Long parentId) {
        Set<Long> permissionIds = new HashSet<>();
        getAllPermissionIdsRecursively(parentId, permissionIds);
        return permissionIds;
    }

    private void getAllPermissionIdsRecursively(Long parentId, Set<Long> permissionIds) {
        QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysPermission::getPermissionParentId, parentId);
        List<SysPermission> permissions = this.list(queryWrapper);

        for (SysPermission permission : permissions) {
            permissionIds.add(permission.getPermissionId());
            getAllPermissionIdsRecursively(permission.getPermissionId(), permissionIds);
        }
    }

    /**
     * 权限启用禁用
     *
     * @param permissionId 权限Id
     * @return 权限启用或禁用的状态值
     */
    @Override
    public ResultVo<SysPermission> enablePermission(Long permissionId) {
        // 根据权限ID获取权限对象
        SysPermission sysPermission = this.getById(permissionId);
        // 切换状态，如果status为null，则设置为默认值1（假设1为启用状态）
        sysPermission.setStatus(sysPermission.getStatus() == 0 ? 1 : 0);
        // 更新权限状态
        if (this.updateById(sysPermission)) {
            return ResultVo.success();
        } else {
            return ResultVo.failure(ResultCode.FAILED);
        }
    }

    /**
     * 根据权限ID查询系统权限信息
     *
     * @param permissionId 用户ID
     * @return 返回对应的系统权限信息对象（sysPermission），如果未找到则返回null
     */
    @Override
    public ResultVo<?> getPermissionByPermissionId(Long permissionId) {
        SysPermission sysPermission = this.getById(permissionId);
        return ResultVo.success(sysPermission);
    }

    /**
     * 权限编辑
     *
     * @param sysPermission 编辑权限对象
     * @return 更新后的权限对象
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo<?> updatePermission(@Validated SysPermission sysPermission) {
        if (this.updateById(sysPermission)) {
            return ResultVo.success();
        }
        return ResultVo.failure(ResultCode.FAILED);

    }

    /**
     * 查询节点以及他的父节点的集合
     *
     * @param permissionName 权限名称
     * @return 构建的权限树
     */

    @Override
    public ResultVo<?> getPermissionsWithParentsByNameLike(String permissionName) {
        // 从数据库中获取模糊匹配的权限列表
        QueryWrapper<SysPermission> queryWrapper = new QueryWrapper<>();
        if (permissionName != null && !permissionName.isEmpty()) {
            queryWrapper.like("permission_name", permissionName);
        }
        List<SysPermission> selectedPermissions = this.list(queryWrapper);

        // 用于存储所有权限（包括自身和父节点）的集合
        Set<SysPermission> allPermissions = new HashSet<>();

        // 遍历每个选中的权限，并递归查找其所有父节点
        for (SysPermission permission : selectedPermissions) {
            List<SysPermission> permissionChain = getParentChain(permission);
            allPermissions.addAll(permissionChain);
        }

        // 转换为列表并返回（如果需要的话，可以根据需求进行排序）
        List<SysPermission> resultList = new ArrayList<>(allPermissions);
        return ResultVo.success(resultList);
    }

    /**
     * 递归查找给定权限的所有父节点，包括自身
     */
    private List<SysPermission> getParentChain(SysPermission permission) {
        List<SysPermission> permissionChain = new ArrayList<>();

        // 从当前权限开始，递归查找父节点
        SysPermission current = permission;
        while (current != null) {
            permissionChain.add(current); // 将当前权限添加到链中
            Long parentId = current.getPermissionParentId();
            if (parentId != null) {
                // 根据父节点ID查找父节点
                current = this.getById(parentId);
            } else {
                // 没有父节点了，结束循环
                current = null;
            }
        }
        Collections.reverse(permissionChain); //将递归得到的权限链进行反转

        return permissionChain;
    }

    /**
     * 根据菜单Id查找权限Id
     *
     * @param menuId 菜单id
     * @return 权限Id集合
     */
    @Override
    public Long getPermissionIdsByMenuId(Long menuId) {
        QueryWrapper<SysPermissionMenu> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("permission_id").eq("menu_id", menuId);
        SysPermissionMenu sysPermission = this.sysPermissionMenuService.getOne(queryWrapper);
        return sysPermission != null ? sysPermission.getPermissionId() : null;
    }
}




